package com.ms.pda.activity.storage


import android.util.Log
import android.view.View
import androidx.databinding.ObservableBoolean
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import com.blankj.utilcode.util.SPUtils
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.listener.OnItemChildClickListener
import com.google.gson.Gson
import com.ms.architecture.base.DataBindingConfig
import com.ms.pda.BR
import com.ms.pda.R
import com.ms.pda.base.ScanActivity
import com.ms.pda.interf.OnDialogCallback
import com.ms.pda.messenger.AppMessenger
import com.ms.pda.messenger.StorageOutMessenger
import com.ms.pda.model.Constants
import com.ms.pda.model.table.StorageOutDO
import com.ms.pda.model.vo.StorageOutVo
import com.ms.pda.utils.DialogUtil
import com.ms.pda.utils.frid.Zebra123FridManager
import com.ms.pda.utils.StringUtils
import com.ms.pda.utils.frid.OnRfidEventsListener
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.lang.Exception
import java.util.Collections
import java.util.Date
import java.util.HashMap
import java.util.HashSet
import java.util.Timer
import kotlin.concurrent.timerTask

class OrderOutActivity : ScanActivity(), OnItemChildClickListener, OnRfidEventsListener {
    companion object {
        const val TAG = "OrderOutActivity"
    }

    private var mState: OrderOutViewModel? = null
    private var mMsger: StorageOutMessenger? = null
    private var mApp: AppMessenger? = null
    private var mFlowJob: Job? = null
    private var fridManager: Zebra123FridManager? = null
//    private var idsSet = Collections.synchronizedSet(HashSet<String>())
//    private var idsSetFinal = Collections.synchronizedSet(HashSet<String>())

    override fun initViewModel() {
        mState = getActivityScopeViewModel(OrderOutViewModel::class.java)
        mMsger = getActivityScopeViewModel(StorageOutMessenger::class.java)
        mApp = getApplicationScopeViewModel(AppMessenger::class.java)
    }

    override fun getDataBindingConfig(): DataBindingConfig? {
        return DataBindingConfig(R.layout.activity_order_out, BR.state, mState!!)
            .addBindingParam(BR.msger, mMsger!!)
            ?.addBindingParam(BR.listener, OrderOutListener())
            ?.addBindingParam(BR.instance, this)
    }

    override fun initViews() {
        super.initViews()
        fridManager = Zebra123FridManager(this, this)
    }

    override fun loadData() {
        fridManager?.connect()

        val lastScanOrder = SPUtils.getInstance().getString(Constants.lastScanOrder, "")
        if (!lastScanOrder.isNullOrEmpty()) {
            val storageOutDO = Gson().fromJson(lastScanOrder, StorageOutDO::class.java)
            mMsger!!.storageOrder.value = storageOutDO
            mState!!.clearEnable.set(true)
            showScanHistory(storageOutDO.orderNo)
        }
    }

    private fun showScanHistory(orderNumber: String?) {
        mFlowJob?.cancel()
        mFlowJob = null
        mFlowJob = lifecycleScope.launch {
            mMsger!!.getStorageOutCode(orderNumber) {
//                it.forEach { storageOutDO ->
//                    idsSet.add(storageOutDO.rfidId!!)
//                    idsSetFinal.addAll(idsSet)
//                }

                Log.i(TAG, "showScanHistory getStorageOutCode size:${it.size}")
                mMsger!!.storageCollection.value = storageDo2Vo(it)
                val count = it.size
                mMsger!!.storageOrder.value?.scanCount = count
                Log.i(TAG, "showScanHistory getStorageOutCode count:${count}")
                mState!!.confirmEnable.set(count > 0)
                Log.i(TAG, "showScanHistory scrollHistory2Bottom")
                scrollHistory2Bottom()
            }
        }
    }

    private fun storageDo2Vo(doList: MutableList<StorageOutDO>): MutableList<StorageOutVo> {
        val voMap = mutableMapOf<String, StorageOutVo>()
        doList.forEach {
            if (voMap.containsKey(it.rfidId)) {
                val storageOutVo = voMap[it.rfidId!!]
                storageOutVo!!.scanCount++
            } else {
                voMap[it.rfidId!!] = StorageOutVo(it.rfidId!!, 1)
            }
        }
        return voMap.values.toMutableList()
    }


    override fun onDestroy() {
        super.onDestroy()
        timer?.cancel()
        fridManager?.onDestroy()
        mFlowJob?.cancel()
        mFlowJob = null
    }

    /**
     * 提交成功重置
     */
    private fun submittedReset() {
        reset()
    }

    /**
     * 清除数据
     */
    private fun reset() {
//        idsSet.clear()
//        idsSetFinal.clear()
        mFlowJob?.cancel()
        mFlowJob = null
        mFlowJob = lifecycleScope.launch {
            mFlowJob?.cancel()
            mFlowJob = null
            mMsger!!.reset(this@OrderOutActivity)
            mState!!.clearEnable.set(false)
            mState!!.scanEnable.set(true)
            mState!!.confirmEnable.set(false)
            SPUtils.getInstance().put(Constants.lastScanOrder, "")
        }
    }


    open inner class OrderOutListener {

        fun handleClear(view: View) {
            DialogUtil.getTipPopupView(
                this@OrderOutActivity,
                getString(R.string.tip_confirm_clear),
                false,
                object : OnDialogCallback {
                    override fun onConfirm() {
                        reset()
                    }

                    override fun onCancel() {
                    }
                })
        }

        fun handleConfirm(view: View) {
            mState!!.scanEnable.set(false)
            DialogUtil.getTipPopupView(
                this@OrderOutActivity,
                getString(R.string.tip_confirm_submit),
                false,
                object : OnDialogCallback {
                    override fun onConfirm() {
                        mMsger!!.storageOrder.value?.orderNo?.let { orderNo ->
                            mFlowJob?.cancel()
                            mFlowJob = null
                            mFlowJob = lifecycleScope.launch {
                                mMsger!!.submitOutOfStock(
                                    this@OrderOutActivity,
                                    orderNo,
                                ) {
                                    mState!!.scanEnable.set(true)
                                    if (it) {
                                        submittedReset()
                                        DialogUtil.getTipPopupView(
                                            this@OrderOutActivity,
                                            this@OrderOutActivity.getString(R.string.tip_out_of_stock_success),
                                            null
                                        )
                                    }
                                }
                            }
                        }
                    }

                    override fun onCancel() {
                        mState!!.scanEnable.set(true)
                    }
                })
        }
    }

    class OrderOutViewModel : ViewModel() {
        val clearEnable: ObservableBoolean = ObservableBoolean(false)
        val scanEnable: ObservableBoolean = ObservableBoolean(true)
        val confirmEnable: ObservableBoolean = ObservableBoolean(false)
    }

    override fun onItemChildClick(adapter: BaseQuickAdapter<*, *>, view: View, position: Int) {

    }

    override fun handleResult(code: String) {
        if (!mState!!.scanEnable.get()) {
            return
        }
        val split = code.split("^")
        if (split.size >= 6) {
            val orderNumber = split[0]
            val distributorName = split[1]
            val productName = split[2]
            val tagColor = split[3]
            val productWidget = split[4]
            val productCount = split[5]
            val storageOutDO = StorageOutDO(
                null,
                null,
                orderNumber,
                distributorName,
                productName,
                productWidget,
                productCount,
                0,
                "",
                tagColor
            )
            val value = mMsger!!.storageOrder.value
            if (value != null && value.orderNo != orderNumber) {
                mFlowJob?.cancel()
                mFlowJob = null
                mFlowJob = lifecycleScope.launch {
                    mMsger!!.clearCatch()
                }
            }
            mMsger!!.storageOrder.value = storageOutDO
            showScanHistory(orderNumber)
            SPUtils.getInstance().put(Constants.lastScanOrder, Gson().toJson(storageOutDO))
            mState!!.clearEnable.set(true)
        }
    }

    private fun addToCatch(newList: MutableList<StorageOutDO>) {
        lifecycleScope.launch {
            mMsger!!.saveCatch(newList)
        }
    }

    private fun scrollHistory2Bottom() {
        val list = mMsger!!.storageCollection.value?.toMutableList()
        list?.size?.let {
            if (it > 0)
                findViewById<RecyclerView>(R.id.rv_content).scrollToPosition(it - 1)
        }
    }

    override fun onRfidConnected() {


    }

    override fun onRfidConnecting() {

    }

    override fun onRfidDisConnected() {
    }

    override fun onRfidSuccess(ids: List<String>) {
        if (!mState!!.scanEnable.get()) {
            Log.i(TAG, "onSuccess orderEnable false")
            return
        }
        addTag(ids)
//        val tagIds = mutableListOf<String>()
//        ids.forEach {
//            if (!idsSet.contains(it)) {
//                idsSet.add(it)
//                tagIds.add(it)
//            }
//        }
//        if (tagIds.size > 0) {
//            addTag(tagIds)
//        }

    }

    var timer: Timer? = null
    var isRfid = false
    override fun onResume() {
        super.onResume()
        test()
    }

    private fun test() {
        timer?.cancel()
        timer = Timer()
        timer!!.schedule(timerTask {
            runOnUiThread {
                if (isRfid) {
                    val list = mutableListOf<String>()
                    for (i in 0 until 30) {
                        list.add("636437643979${(Math.random() * 100).toInt()}D")
                    }
                    onRfidSuccess(list)
                } else {
                    isRfid = !isRfid
                    handleResult("TEST20170315^测试用经销商名称^硫酸钾型 15-15-15^黄色^700^14000")
                }
            }
        }, 2000, 5000)
    }


    override fun onRfidFailure(exception: Exception) {
    }

    private fun findOldStorageOuVoHistory(tagId: String): StorageOutVo? {
        val voHistoryList = mMsger!!.storageCollection.value ?: mutableListOf()
        voHistoryList.forEach { storageOutVo ->
            if (storageOutVo.rfidId == tagId) {
                return storageOutVo
            }
        }
        return null
    }

    private fun addTag(tagIds: List<String>) {
        val storageOutDO = mMsger!!.storageOrder.value

        if (storageOutDO != null) {
            storageOutDO.scanCount += tagIds.size
            Log.i(TAG, "刷新已扫数量：${storageOutDO.scanCount}")
            val newList = mutableListOf<StorageOutDO>()
            val newVoList = mutableListOf<StorageOutVo>()

            val createTime = StringUtils.date2String(Date(), "yyyy-MM-dd HH:mm:ss")
            tagIds.forEachIndexed { index, tagId ->
                newList.add(
                    StorageOutDO(
                        null,
                        tagId,
                        storageOutDO.orderNo,
                        storageOutDO.distributorName,
                        storageOutDO.productName,
                        storageOutDO.productWidget,
                        storageOutDO.productCount,
//                        size,
                        1,
                        createTime,
                        storageOutDO.tagColor,
                    )
                )
                val oldStorageOuVo = findOldStorageOuVoHistory(tagId)
                if (oldStorageOuVo != null) {
                    oldStorageOuVo.scanCount++
                } else {
                    newVoList.add(StorageOutVo(tagId, 1))
                }
            }

            Log.i(TAG, "添加数据")
            mMsger!!.storageCollection.value?.addAll(newVoList)

            mMsger!!.storageOrder.value = storageOutDO
            mState!!.clearEnable.set(true)
            mState!!.confirmEnable.set(true)
            Log.i(TAG, "添加数据后滚动到最低")
            scrollHistory2Bottom()
            addToCatch(newList)
        }
    }

}